/*
通用功能类，与业务无关的功能实现
1.获取系统时间
2.判断文件是否存在
3.获取文件的所在目录路径
4.创建目录
*/
#ifndef __M_UTIL_H__
#define __M_UTIL_H__

#include <iostream>
#include <string>
#include <sys/stat.h>
#include <sys/types.h>

namespace bitlog {
    namespace util {
        class Date {
        public:
            static size_t now() {
                return time(nullptr);
            }
        };

        class File {
        public:
            // 判断文件是否存在
            static bool exists(const std::string& pathname) {
                struct stat st;
                return stat(pathname.c_str(), &st) == 0;
            }

            // 获取文件的所在目录路径/home/abc/test/a.txt或者a.txt
            static std::string path(const std::string& pathname) {
                size_t pos = pathname.find_last_of("/\\");
                if (pos == std::string::npos) // a.txt
                    return ".";
                return pathname.substr(0, pos + 1); // /home/abc/test/
            }

            // 创建目录
            // 测试样例：
            // /home/abc/test/  	/home/abc/test
            // text    		test/
            // ./test  		./test/
            static void createDirectory(const std::string& pathname) {
                if (pathname.empty())
                    return; // 如果路径为空，则直接返回，不做任何操作。
                if (exists(pathname))
                    return; // 检查路径是否已经存在，如果存在则直接返回。

                size_t pos, idx = 0; // 初始化变量idx和pos为0。idx表示搜索的起始位置，pos表示当前处理的位置。

                // 循环遍历路径字符串，直到索引超出字符串长度。
                while (idx < pathname.size()) {
                    pos = pathname.find_first_of("/\\", idx); // 查找从当前位置开始的第一个斜杠或反斜杠的位置。
                    // 如果找不到更多的分隔符，说明已经到达最后一个子目录或文件名。
                    if (pos == std::string::npos) {
                        mkdir(pathname.c_str(), 0755); // 创建最终的目录。
                        return;
                    }
                    // 如果找到的分隔符正好位于当前索引位置，说明这是一个连续的分隔符，跳过它。
                    if (pos == idx) {
                        idx = pos + 1;
                        continue;
                    }

                    std::string subdir = pathname.substr(0, pos); // 截取从开头到当前分隔符位置的子串作为子目录。
                    // 跳过当前目录（"."）和上一级目录("..")。
                    if (subdir == "." || subdir == "..") {
                        idx = pos + 1;
                        continue;
                    }
                    // 检查子目录是否已经存在，如果存在则跳过创建步骤。
                    if (exists(subdir)) {
                        idx = pos + 1;
                        continue;
                    }
                    mkdir(subdir.c_str(), 0755); // 创建子目录。
                    idx = pos + 1;               // 更新索引为下一个字符的位置。
                }
            }
        };
    }
}

#endif